﻿using PaddleOCRSharp;
using Prism.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using Tools.Core.Dtos;
using static System.Net.Mime.MediaTypeNames;

namespace Tools.Core
{
    public class Softwares
    {
        public static class EngineFactory
        {
            private static PaddleOCREngine engine = null;
            private static PaddleStructureEngine structureEngine = null;
            public static PaddleOCREngine GetEngine()
            {
                if (engine == null)
                {
                    engine = new PaddleOCREngine();
                }
                return engine;
            }
            public static PaddleStructureEngine GetStructureEngine()
            {
                if(structureEngine == null)
                {
                    structureEngine = new PaddleStructureEngine();
                }
                return structureEngine;
            }
        }
        public static string GetAccessPassword(string filePath)
        {
            byte[] array = new byte[16]
            {
                190, 236, 101, 156, 254, 40, 43, 138, 108, 123,
                205, 223, 79, 19, 247, 177
            };
            byte b = 12;
            string text = "";
            try
            {
                FileStream fileStream = File.OpenRead(filePath);
                fileStream.Seek(20L, SeekOrigin.Begin);
                byte b2 = (byte)fileStream.ReadByte();
                fileStream.Seek(66L, SeekOrigin.Begin);
                byte[] array2 = new byte[33];
                if (fileStream.Read(array2, 0, 33) != 33)
                {
                    return "";
                }
                byte b3 = (byte)(array2[32] ^ b);
                for (int i = 0; i < 16; i++)
                {
                    byte b4 = (byte)(array[i] ^ array2[i * 2]);
                    if (i % 2 == 0 && b2 == 1)
                    {
                        b4 = (byte)(b4 ^ b3);
                    }
                    if (b4 > 0)
                    {
                        string obj = text;
                        char c = (char)b4;
                        text = obj + c;
                    }
                }
                return text;
            }
            catch
            {
                return "解析失败";
            }
        }
        
        public static void OCRImages(IEnumerable<ImageOCRPlanDto> plans)
        {
            foreach (var plan in plans)
            {
                plan.StartTime=DateTime.Now;
                plan.Result= EngineFactory.GetEngine().DetectText(plan.FromPath).Text;
                plan.Completed= true;
                plan.EndTime = DateTime.Now;
            }
        }
        public static string OCRText(string imagePath)
        {
            return EngineFactory.GetEngine().DetectText(imagePath).Text;
        }
        public static string OCRTable(string imagePath)
        {
            return EngineFactory.GetStructureEngine().StructureDetectFile(imagePath);
        }
        public static bool SendMails(MailSenderDto sender,MailReceiverDto receiver,Dtos.MailMessageDto message)
        {
            SmtpClient client=new SmtpClient();
            client.DeliveryMethod = SmtpDeliveryMethod.Network;
            client.Host = sender.Host;
            client.EnableSsl = true;
            client.UseDefaultCredentials= true;
            client.Credentials = new NetworkCredential(sender.Account, sender.Password);

            System.Net.Mail.MailMessage mail = new System.Net.Mail.MailMessage(sender.Account, receiver.To);
            mail.Subject= message.Subject;
            mail.Body = message.Body;
            mail.BodyEncoding = Encoding.UTF8;
            mail.IsBodyHtml = message.IsBodyHtml;
            mail.Priority = MailPriority.Normal;
            try
            {
                client.Send(mail);
                return true;
            }
            catch
            {
                return false;
            }
        }
        public static void ConvertImages(IEnumerable<ImageConvertPlanDto> plans)
        {
            
            foreach(var plan in plans)
            {
                if (!Directory.Exists(plan.OutputDir))
                {
                    Directory.CreateDirectory(plan.OutputDir);
                }
                plan.ToPath = GetTargetPath(plan.OutputDir,Path.GetFileNameWithoutExtension(plan.FromPath),plan.TargetType);
                var type = plan.TargetType.ToLower();
                plan.StartTime = DateTime.Now;
                Bitmap b = new Bitmap(plan.FromPath);
                switch (type)
                {
                    case "png":
                        b.Save(plan.ToPath, ImageFormat.Png);break;
                    case "jpg":
                    case "jpeg":
                        b.Save(plan.ToPath,ImageFormat.Jpeg);break;
                    case "bmp":
                        b.Save(plan.ToPath,ImageFormat.Bmp);break;
                    case "gif":
                        b.Save(plan.ToPath, ImageFormat.Gif);break;
                    case "ico":
                        b.Save(plan.ToPath,ImageFormat.Icon);break;
                    case "emf":
                        b.Save(plan.ToPath,ImageFormat.Emf);break;
                    case "exif":
                        b.Save(plan.ToPath,ImageFormat.Exif);break;
                    case "tiff":
                        b.Save(plan.ToPath,ImageFormat.Tiff);break;
                    case "wmf":
                        b.Save(plan.ToPath ,ImageFormat.Wmf);break;
                    default:
                        MessageBox.Show("不支持此格式", "提示",MessageBoxButton.OK,MessageBoxImage.Warning);
                        break;
                }
                plan.Completed = true;
                plan.EndTime = DateTime.Now;
            }
        }

        public static void ConvertVideos(IEnumerable<VideoConvertPlanDto> plans)
        {
            foreach (var plan in plans)
            {
                if (!Directory.Exists(plan.OutputDir))
                {
                    Directory.CreateDirectory(plan.OutputDir);
                }
                plan.ToPath = GetTargetPath(plan.OutputDir, Path.GetFileNameWithoutExtension(plan.FromPath), plan.TargetType);
                CMD("ffmpeg", $"-i {plan.FromPath} {plan.ToPath}", () =>
                {
                    plan.Completed = true;
                });
            }
        }
        public static string GetTargetPath(string outputDir,string name,string ext)
        {
            int i = 0;
            var path = Path.Combine(outputDir, $"{name}.{ext}");
            while (File.Exists(path))
            {
                path= Path.Combine(outputDir, $"{name}.{++i}.{ext}");
            }
            return path;
        }
        public static string FormatCode(string code)
        {
            string tempPath=Path.GetTempFileName();
            File.WriteAllText(tempPath, code);
            CMD("astyle", $"--style=allman \"{tempPath}\"", null);
            var formattedCode = File.ReadAllText(tempPath);
            File.Delete(tempPath);
            return formattedCode;

        }
        public static void CMD(string command,string arguments,Action action)
        {
            ProcessStartInfo p = new ProcessStartInfo()
            {
                FileName=command,
                Arguments=arguments,
                UseShellExecute=false,
                CreateNoWindow=true,
                RedirectStandardOutput=false,
                RedirectStandardError=true,
                RedirectStandardInput=false
            };
            using (Process process = new Process {
                StartInfo=p
            })
            {
                try
                {
                    process.ErrorDataReceived += (sender, e) =>
                    {
                        Console.WriteLine(e.Data);
                    };
                    
                    process.Start();
                    process.BeginErrorReadLine();
                    process.WaitForExit();
                    action?.Invoke();
                }
                catch(Exception ex)
                {
                    MessageBox.Show(ex.Message); 
                }
            }
        }
    }
}
